home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / dev / lang / ace102.lha / TinyBASIC / TinyBASIC.b < prev    next >
Text File  |  1993-03-25  |  15KB  |  871 lines

  1. { ** Tiny BASIC Interpreter ** 
  2.  
  3.   Author: David Benn
  4.     Date: 21st,22nd March 1992,
  5.         26th-29th January 1993,
  6.       25th March 1993 }
  7.  
  8. version$="$VER: TinyBASIC 1.0 29 01 1993"
  9.  
  10. library exec
  11.  
  12. declare function AllocMem& library exec
  13. declare function FreeMem library exec
  14.  
  15. '..memory constants
  16. const MEMF_PUBLIC=1&
  17. const MEMF_CLEAR=65536
  18. const NULL=0&
  19.  
  20. '..boolean constants
  21. const true=-1&
  22. const false=0&
  23.  
  24. '..stack 
  25. const maxstack=100
  26. dim stack(maxstack)
  27. shortint stacktop
  28.  
  29. '..intrinsic functions
  30. const maxfunc=8
  31. dim funcs$(maxfunc)
  32.  
  33. for i%=1 to maxfunc
  34.   read funcs$(i%)
  35. next
  36.  
  37. data "SIN","COS","TAN","LOG","SQR","FIX","INT","RND"
  38.  
  39. { * tokens * }
  40. const maxsym=34
  41.  
  42. '..special symbols
  43. const alpha=1
  44. const number=2
  45. const stringliteral=3
  46. const plus=4
  47. const minus=5
  48. const mult=6
  49. const div=7
  50. const pow=8
  51. const lparen=9
  52. const rparen=10
  53. const eq=11
  54. const lt=12
  55. const gt=13
  56. const ltoreq=14
  57. const gtoreq=15
  58. const noteq=16
  59. const comma=17
  60. const colon=18
  61. const eos=19
  62.  
  63. '..reserved words
  64. const clssym=20
  65. const elsesym=21
  66. const gotosym=22
  67. const ifsym=23
  68. const inputsym=24
  69. const letsym=25
  70. const listsym=26
  71. const loadsym=27
  72. const newsym=28
  73. const printsym=29
  74. const runsym=30
  75. const savesym=31
  76. const stopsym=32
  77. const thensym=33
  78.  
  79. const undef=maxsym
  80.  
  81. '..token strings
  82. dim sym.name$(maxsym)
  83. {for i%=1 to maxsym
  84.  read sym.name$(i%)
  85. next
  86. data alpha,number,stringliteral
  87. data "+","-","*","/","^"
  88. data "(",")","=","<",">","<=",">=","<>",",",":",eos
  89. data "cls","else","goto","if","input","let","list","load"
  90. data "new","print ","run","save","stop","then"
  91. data undef}
  92.  
  93. '..reserved words
  94. const maxword=14
  95. dim word$(maxword)
  96.  
  97. for i%=1 to maxword
  98.   read word$(i%)
  99. next
  100.  
  101. data "CLS","ELSE","GOTO","IF","INPUT","LET","LIST"
  102. data "LOAD","NEW","PRINT","RUN","SAVE","STOP","THEN"
  103.  
  104. '..errors
  105. longint bad
  106. const DIVBYZERO=1
  107. const SYNTAX=2
  108. const STKOVFL=3
  109. const STKUFL=4
  110. const LINEOUTOFRANGE=5
  111. const NOSUCHLINE=6
  112. const OUTOFMEMORY=7
  113. const CANNOTOPENFILE=8
  114. const FILENOTFOUND=9
  115.  
  116. '..program lines
  117. const maxlines=1000
  118. dim code_ptr&(maxlines)
  119.  
  120. for i%=0 to maxlines
  121.   code_ptr&(i%)=NULL
  122. next
  123. shortint topline
  124.  
  125. '..program counter
  126. shortint pc,old_pc
  127.  
  128. '..miscellaneous globals
  129. shortint n,length
  130. longint halt_requested
  131. ch$=""
  132. ut_ch$=""
  133. buf$=""
  134. ut_buf$=""
  135. obj$=""
  136. sym=undef
  137.  
  138. '..variables
  139. dim var(25)
  140. for i%=0 to 25
  141.  var(i%)=0
  142. next
  143.     
  144. '..forward references
  145. declare SUB expr
  146. declare SUB statement
  147. declare SUB parse_line
  148.  
  149. '..enable CTRL-C breaks
  150. ON BREAK GOTO start
  151. BREAK ON
  152.  
  153. {SUB show.sym(n)
  154. shared sym.name$
  155.   print sym.name$(n)
  156. END SUB}
  157.  
  158. SUB er(n)
  159. shared bad,pc,old_pc
  160.   if bad then exit sub    '..report only 1 error per line
  161.   case
  162.     n=DIVBYZERO     : print "DIVISION BY ZERO";
  163.     n=SYNTAX        : print "SYNTAX ERROR";
  164.     n=STKOVFL        : print "STACK OVERFLOW";
  165.     n=STKUFL        : print "STACK UNDERFLOW";
  166.     n=LINEOUTOFRANGE    : print "LINE OUT OF RANGE 1 TO";str$(maxlines); 
  167.     n=NOSUCHLINE    : print "LINE DOES NOT EXIST";
  168.     n=OUTOFMEMORY    : print "OUT OF MEMORY";
  169.     n=CANNOTOPENFILE    : print "CAN'T OPEN FILE FOR WRITING";
  170.     n=FILENOTFOUND    : print "FILE NOT FOUND";
  171.   end case
  172.   if pc<>0 then print " IN LINE";old_pc else print
  173.   bad=true
  174. END SUB
  175.  
  176. SUB nextch
  177. shared ch$,ut_ch$,buf$,ut_buf$,n,length
  178.  
  179.   if n<=length then
  180.     ch$=mid$(buf$,n,1)
  181.     ut_ch$=mid$(ut_buf$,n,1)
  182.     ++n
  183.   else
  184.     ch$=""
  185.   end if 
  186. END SUB
  187.  
  188. SUB rsvd.wd%(x$)
  189. shared word$
  190. shortint i,num
  191.  
  192.   i=1
  193.   while i<=maxword and num=0
  194.     if x$ = word$(i) then num=i
  195.     ++i
  196.   wend
  197.  
  198.   if num=0 then rsvd.wd%=alpha else rsvd.wd%=num+eos
  199. END SUB
  200.  
  201. SUB insymbol
  202. shared ch$,ut_ch$,sym,obj$
  203. shortint periods
  204.  
  205.  obj$=""
  206.  sym=undef
  207.  
  208.  '...skip whitespace
  209.  if ch$<=" " and ch$<>"" then
  210.    repeat
  211.      nextch
  212.    until ch$>" " or ch$=""
  213.  end if
  214.  
  215.  '..end of string?
  216.  if ch$="" then sym=eos:exit sub
  217.  
  218.  '...characters
  219.  if ch$>="A" and ch$<="Z" then
  220.    while ch$>="A" and ch$<="Z"
  221.      obj$=obj$+ch$   
  222.      nextch 
  223.    wend
  224.    sym=rsvd.wd%(obj$)
  225.  else  
  226.    '...unsigned numeric constant
  227.    if (ch$>="0" and ch$<="9") or ch$="." then
  228.      sym=number
  229.      while (ch$>="0" and ch$<="9") or ch$="."
  230.        if ch$="." then ++periods
  231.        obj$=obj$+ch$
  232.        nextch
  233.      wend
  234.      if periods > 1 then 
  235.        sym=undef
  236.        er(SYNTAX)
  237.      end if
  238.    else
  239.      '..string literal
  240.      if ch$=chr$(34) then
  241.        sym=stringliteral
  242.        nextch
  243.        while ch$<>chr$(34) and ch$<>""
  244.      obj$=obj$+ut_ch$
  245.          nextch
  246.        wend
  247.        if ch$<>chr$(34) then call er(SYNTAX):sym=undef:exit sub
  248.        nextch    
  249.      else
  250.        '...single character
  251.        obj$=ch$
  252.        case
  253.          obj$="+" : sym=plus
  254.          obj$="-" : sym=minus
  255.          obj$="*" : sym=mult
  256.          obj$="/" : sym=div
  257.          obj$="^" : sym=pow
  258.          obj$="(" : sym=lparen
  259.          obj$=")" : sym=rparen
  260.          obj$="=" : sym=eq
  261.          obj$="<" : sym=lt
  262.          obj$=">" : sym=gt
  263.      obj$="," : sym=comma
  264.      obj$=":" : sym=colon
  265.        end case
  266.  
  267.        nextch
  268.     
  269.        '..<= <> >= ?
  270.        if sym=lt and ch$="=" then 
  271.          sym=ltoreq:nextch
  272.        else
  273.          if sym=lt and ch$=">" then 
  274.            sym=noteq:nextch
  275.          else
  276.            if sym=gt and ch$="=" then 
  277.              sym=gtoreq:nextch
  278.            end if
  279.          end if
  280.        end if
  281.  
  282.        if sym=undef then call er(SYNTAX)
  283.      end if
  284.    end if
  285.  end if
  286.  
  287.  'show.sym(sym)
  288. END SUB
  289.  
  290. SUB push(x)
  291. shared stacktop,stack
  292.  
  293.   if stacktop>maxstack then 
  294.     er(STKOVFL)
  295.   else
  296.     stack(stacktop)=x
  297.     ++stacktop
  298.   end if
  299. END SUB
  300.  
  301. SUB pop
  302. shared stacktop,stack
  303.  
  304.   --stacktop
  305.   if stacktop<0 then 
  306.     er(STKUFL) 
  307.   else
  308.     pop=stack(stacktop)
  309.   end if
  310. END SUB
  311.  
  312. SUB func
  313. shared funcs$,obj$,sym,bad
  314. longint found
  315. shortint funct
  316.  
  317.   '..search for the function.
  318.   found=false
  319.   i=1
  320.   while i<=maxfunc and not found
  321.     if funcs$(i) = obj$ then funct=i:found=true else ++i
  322.   wend
  323.  
  324.   if funct then 
  325.     '..function
  326.     fun$=funcs$(funct)
  327.   else
  328.     '..variable
  329.     func=0
  330.     exit sub
  331.   end if
  332.  
  333.   '...push the argument
  334.   if funct<8 then
  335.     insymbol
  336.     if sym<>lparen then 
  337.       er(SYNTAX)
  338.       funct=0
  339.     else
  340.       insymbol
  341.       expr
  342.       if bad then func=0:exit sub
  343.       if sym<>rparen then call er(SYNTAX):funct=0
  344.     end if
  345.   end if
  346.  
  347.   '...execute function
  348.   case
  349.     funct=1 : push(sin(pop))
  350.     funct=2 : push(cos(pop))
  351.     funct=3 : push(tan(pop))
  352.     funct=4 : push(log(pop))
  353.     funct=5 : push(sqr(pop))
  354.     funct=6 : push(fix(pop))
  355.     funct=7 : push(clng(pop))
  356.     funct=8 : push(rnd)
  357.   end case
  358.  
  359.   func=-1
  360. END SUB
  361.  
  362. SUB var_index%(x$)
  363.   var_index% = asc(x$)-asc("A")  
  364. END SUB
  365.  
  366. SUB factor
  367. shared sym,obj$,bad,var
  368.  
  369.   if sym=number then 
  370.     '..numeric literal
  371.     push(val(obj$))
  372.   else
  373.     '..parenthesised expression?
  374.     if sym=lparen then
  375.       insymbol
  376.       if sym=eos then call er(SYNTAX):exit sub
  377.       expr
  378.       if bad then exit sub
  379.       if sym<>rparen then call er(SYNTAX):exit sub
  380.     else  
  381.       '..function or variable?
  382.       if not func then 
  383.         if sym=alpha then 
  384.           push(var(var_index%(obj$)))
  385.         else
  386.           '..unknown
  387.           er(SYNTAX)
  388.     end if
  389.       end if
  390.     end if
  391.   end if
  392.  
  393.   insymbol
  394. END SUB
  395.  
  396. SUB expterm
  397. shared sym,bad
  398.   factor
  399.   while sym=pow
  400.     insymbol
  401.     factor
  402.     if bad then exit sub
  403.     op2=pop
  404.     op1=pop
  405.     push(op1^op2)
  406.   wend
  407. END SUB
  408.  
  409. SUB negterm
  410. shared sym,bad
  411. longint negate
  412.   negate=false
  413.   if sym=minus then 
  414.     negate=true
  415.     insymbol
  416.   else
  417.     if sym=plus then 
  418.       insymbol
  419.     end if
  420.   end if
  421.   expterm
  422.   if bad then exit sub
  423.   if negate then call push(-pop)  
  424. END SUB
  425.  
  426. SUB term
  427. shared sym,bad
  428. shortint op
  429.   negterm
  430.   while sym=mult or sym=div
  431.     op=sym
  432.     insymbol
  433.     negterm
  434.     if bad then exit sub
  435.     op2=pop
  436.     op1=pop
  437.     if op=mult then
  438.       push(op1*op2)
  439.     else
  440.       if op2<>0 then 
  441.         push(op1/op2) 
  442.       else 
  443.         er(DIVBYZERO)
  444.       end if
  445.     end if
  446.   wend
  447. END SUB
  448.  
  449. SUB simple_expr
  450. shared sym,bad
  451. shortint op
  452.   term
  453.   while sym=plus or sym=minus
  454.     op=sym
  455.     insymbol
  456.     term
  457.     if bad then exit sub
  458.     op2=pop
  459.     op1=pop
  460.     if op=plus then
  461.       push(op1+op2)
  462.     else
  463.       push(op1-op2) 
  464.     end if
  465.   wend  
  466. END SUB
  467.  
  468. SUB expr
  469. shared sym,bad
  470. shortint op
  471.   simple_expr
  472.   while sym=eq or sym=lt or sym=gt or sym=ltoreq or sym=gtoreq or sym=noteq
  473.     op=sym
  474.     insymbol
  475.     simple_expr
  476.     if bad then exit sub
  477.     op2=pop
  478.     op1=pop
  479.     case
  480.       op=eq     : push(op1=op2)
  481.       op=lt     : push(op1<op2)
  482.       op=gt     : push(op1>op2)
  483.       op=ltoreq : push(op1<=op2)
  484.       op=gtoreq : push(op1>=op2)
  485.       op=noteq  : push(op1<>op2)
  486.     end case
  487.   wend  
  488. END SUB
  489.  
  490. SUB assign_to_variable
  491. shared sym,bad,obj$,var
  492.  
  493.  '..variable assignment
  494.  insymbol
  495.  if sym<>alpha then 
  496.    er(SYNTAX)
  497.    exit sub
  498.  end if
  499.  variable$=obj$
  500.  insymbol
  501.  if sym=eq then
  502.    insymbol
  503.    if sym=eos then call er(SYNTAX):exit sub
  504.    expr
  505.    if bad then exit sub else var(var_index%(variable$))=pop
  506.  end if
  507. END SUB
  508.  
  509. SUB if_statement
  510. shared sym,bad
  511.  
  512.   '..IF-THEN-ELSE
  513.   insymbol
  514.   expr
  515.   if bad then exit sub 
  516.   '..THEN
  517.   if sym=thensym then
  518.     if pop=-1 then
  519.       insymbol
  520.       statement
  521.       while sym<>eos:insymbol:wend
  522.     else
  523.       while sym<>elsesym and sym<>eos
  524.         insymbol
  525.       wend
  526.       '..ELSE (optional)
  527.       if sym=elsesym then
  528.         insymbol
  529.      statement
  530.       end if         
  531.     end if
  532.   else
  533.     er(SYNTAX)
  534.   end if
  535. END SUB
  536.  
  537. SUB modify_program(num%)
  538. shared sym,buf$,ut_buf$,code_ptr&
  539. shared n,length,topline
  540. longint strptr
  541.  
  542.  { kill or modify a program line }
  543.  
  544.  '..free memory associated with line num%?
  545.  '..(have to do this whether we are 
  546.  '...killing OR replacing a line). 
  547.  
  548.  if num%<1 or num%>maxlines then call er(LINEOUTOFRANGE):exit sub
  549.  
  550.  strptr=code_ptr&(num%)
  551.  if strptr then
  552.    FreeMem(strptr,len(cstr(strptr))+1&)
  553.    code_ptr&(num%)=NULL
  554.  end if  
  555.    
  556.  if n<=length then
  557.    '..** replace line num% if in range **
  558.    if num%>=1 and num%<=maxlines then
  559.      x$=mid$(ut_buf$,n)
  560.      '..check for string literals and don't
  561.      '..change the case of their characters.
  562.      y$=""
  563.      i%=1
  564.      ln%=len(x$)
  565.      while i%<=ln%
  566.        c$=mid$(x$,i%,1)
  567.        if c$=chr$(34) then
  568.          y$=y$+c$
  569.          repeat
  570.            ++i%
  571.            c$=mid$(x$,i%,1)
  572.            if c$<>chr$(34) then y$=y$+c$
  573.          until c$=chr$(34) or i%=ln%
  574.          y$=y$+c$
  575.          ++i%
  576.        else
  577.          y$=y$+ucase$(c$)
  578.          ++i%
  579.        end if
  580.      wend 
  581.      x$=y$
  582.  
  583.      '..allocate memory for line and store it.     
  584.      strptr=AllocMem(len(x$)+1&,MEMF_PUBLIC or MEMF_CLEAR)
  585.      if strptr=NULL then call er(OUTOFMEMORY):exit sub
  586.      string basic_line address strptr
  587.      basic_line=x$
  588.      code_ptr&(num%)=strptr 
  589.      if num%>topline then topline=num%
  590.    else
  591.      er(LINEOUTOFRANGE)  
  592.    end if      
  593.  else
  594.    '..find next lowest non-null line 
  595.    '..after removal of highest line.
  596.    if num%=topline then
  597.      repeat
  598.        --num%
  599.      until code_ptr&(num%)<>NULL or num%<1
  600.      topline=num%  '..code_ptr&(0) is sentinel.
  601.    end if
  602.  end if   
  603. END SUB
  604.  
  605. SUB list_program
  606. shared code_ptr&,topline
  607. longint strptr
  608.  
  609.   { list current program }
  610.  
  611.   i%=1
  612.   while i%<=topline
  613.     num$=str$(i%)
  614.     num$=right$(num$,len(num$)-1&)
  615.     strptr=code_ptr&(i%)
  616.     if strptr then print num$;" ";cstr(strptr) 
  617.     ++i%     
  618.   wend  
  619. END SUB
  620.  
  621. SUB clear_program
  622. shared code_ptr&,topline
  623. longint strptr
  624.  
  625.   { clear program memory }
  626.  
  627.   for i%=0 to maxlines
  628.     strptr=code_ptr&(i%)
  629.     if strptr then
  630.       FreeMem(strptr,len(cstr(strptr))+1&)
  631.       code_ptr&(i%)=NULL
  632.     end if
  633.   next
  634.  
  635.   topline=0
  636. END SUB
  637.  
  638. SUB run_program
  639. shared code_ptr&,pc,old_pc,buf$,ut_buf$
  640. shared bad,topline,halt_requested
  641. longint strptr
  642.  
  643.  { execute current program }
  644.  
  645.  if topline<1 then exit sub
  646.  
  647.  pc=1
  648.  repeat
  649.    strptr=code_ptr&(pc)
  650.    old_pc=pc
  651.    ++pc
  652.    if strptr then
  653.      buf$=cstr(strptr)
  654.      ut_buf$=buf$
  655.      parse_line
  656.    end if
  657.  until bad or halt_requested or pc>topline
  658. END SUB
  659.  
  660. SUB load_program
  661. shared sym,obj$,code_ptr&
  662. shared topline
  663. longint strptr
  664.  
  665.  { load program from file }
  666.  
  667.  insymbol
  668.  if sym=stringliteral then
  669.    open "I",#2,obj$
  670.    if handle(2)<>NULL then 
  671.      clear_program
  672.      print "LOADING ";obj$;".. ";
  673.      while not eof(2)
  674.        input #2,num%
  675.        line input #2,x$
  676.        strptr=AllocMem(len(x$)+1&,MEMF_PUBLIC or MEMF_CLEAR)
  677.        if strptr=NULL then call er(OUTOFMEMORY):close #2:exit sub
  678.        string basic_line address strptr
  679.        basic_line=x$
  680.        code_ptr&(num%)=strptr 
  681.        if num%>topline then topline=num%    
  682.      wend        
  683.      close #2
  684.      print "PROGRAM LOADED."
  685.    else
  686.      er(FILENOTFOUND)
  687.    end if
  688.  else
  689.    er(SYNTAX)
  690.  end if    
  691. END SUB
  692.  
  693. SUB save_program
  694. shared sym,obj$,code_ptr&
  695. shared topline
  696. longint strptr
  697.  
  698.  { store current program in file }
  699.  
  700.  if topline<1 then exit sub
  701.  
  702.  insymbol
  703.  if sym=stringliteral then
  704.    open "O",#3,obj$
  705.    if handle(3)<>NULL then 
  706.      print "SAVING ";obj$;".. ";
  707.      for i%=1 to topline
  708.        strptr=code_ptr&(i%)
  709.        if strptr then print #3,i%;cstr(strptr)
  710.      next
  711.      print "PROGRAM SAVED."
  712.      close #3
  713.    else
  714.      er(CANNOTOPENFILE)
  715.    end if
  716.  else
  717.    er(SYNTAX)
  718.  end if    
  719. END SUB
  720.  
  721. SUB statement
  722. shared sym,bad,obj$,var,pc,code_ptr&
  723. shared halt_requested
  724.  
  725.  '..EMPTY STATEMENT
  726.  if sym=eos then exit sub
  727.  
  728.  '..NUMBER
  729.  if sym=number then 
  730.    modify_program(fix(val(obj$)))
  731.    exit sub
  732.  end if
  733.   
  734.  '..CLS
  735.  if sym=clssym then cls:exit sub
  736.  
  737.  '..GOTO
  738.  if sym=gotosym then 
  739.    insymbol
  740.    if sym=eos then call er(SYNTAX):exit sub
  741.    expr
  742.    if not bad then pc=pop else exit sub
  743.    if pc<1 or pc>maxlines then call er(LINEOUTOFRANGE)
  744.    if code_ptr&(pc)=NULL then call er(NOSUCHLINE)
  745.    exit sub
  746.  end if
  747.  
  748.  '..IF
  749.  if sym=ifsym then 
  750.    if_statement
  751.    exit sub
  752.  end if
  753.  
  754.  '..INPUT
  755.  if sym=inputsym then
  756.    insymbol
  757.    if sym=alpha then 
  758.      input var(var_index%(obj$)) 
  759.    else 
  760.      er(SYNTAX)
  761.    end if
  762.    exit sub
  763.  end if
  764.  
  765.  '..LET
  766.  if sym=letsym then
  767.    assign_to_variable
  768.    exit sub
  769.  end if
  770.  
  771.  '..LIST  
  772.  if sym=listsym then
  773.    list_program
  774.    exit sub
  775.  end if
  776.  
  777.  '..LOAD
  778.  if sym=loadsym then
  779.    load_program
  780.    exit sub
  781.  end if
  782.  
  783.  '..NEW
  784.  if sym=newsym then 
  785.    clear_program
  786.    exit sub
  787.  end if
  788.  
  789.  '..PRINT
  790.  if sym=printsym then
  791.    repeat
  792.      insymbol
  793.      if sym=eos then call er(SYNTAX):exit sub
  794.      if sym=stringliteral then 
  795.        print obj$;
  796.        insymbol
  797.      else
  798.        expr
  799.        if not bad then print pop;
  800.      end if
  801.    until sym<>comma
  802.    print
  803.    exit sub
  804.  end if
  805.  
  806.  '..RUN 
  807.  if sym=runsym then
  808.    run_program
  809.    exit sub
  810.  end if
  811.  
  812.  '..SAVE
  813.  if sym=savesym then
  814.    save_program
  815.    exit sub
  816.  end if
  817.  
  818.  '..STOP
  819.  if sym=stopsym then
  820.    halt_requested=true
  821.    exit sub    '..see run_program
  822.  end if
  823.  
  824.  '..UNKNOWN 
  825.  er(SYNTAX)
  826. END SUB
  827.  
  828. SUB parse_line
  829. shared sym,bad,buf$
  830. shared ch$,n,length,stacktop
  831. shared halt_requested
  832.   ch$=" " 
  833.   n=1
  834.   length=len(buf$)
  835.   bad=false
  836.   halt_requested=false    
  837.   stacktop=1
  838.   repeat
  839.     insymbol
  840.     statement
  841.     if sym<>colon and sym<>eos then call insymbol
  842.   until sym<>colon
  843. END SUB
  844.  
  845. SUB finished
  846. shared buf$
  847.  
  848.  '..Quit,Exit?
  849.  if instr(buf$,"QUIT") or instr(buf$,"EXIT") or instr(buf$,"SYSTEM") then 
  850.    finished=true
  851.  else
  852.    finished=false
  853.  end if
  854. END SUB
  855.  
  856. { ** MAIN ** }
  857. window 1,"** Tiny BASIC Interpreter © 1993 David Benn **",(0,0)-(640,200)
  858.  
  859. repeat
  860.  start:
  861.   pc=0
  862.   input ,ut_buf$
  863.   buf$=ucase$(ut_buf$)
  864.   if not finished then call parse_line
  865. until finished
  866.  
  867. window close 1
  868.  
  869. clear_program
  870. library close exec
  871.